package com.api.sdk;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

@Component
@Slf4j
public class ApiClient {
    @Autowired
    public ApiConfig apiConfig;
    private HttpRequestUtil httpRequestUtil;
    private ApiFieldProcess apiFieldProcess;
    private JsonParseUtil jsonParseUtil;

    /**
     * 响应超时60s
     */
    public static final int RESPONSE_TIMEOUT_MILLISECONDS = 100000 * 60;

    /**
     * 添加请求头
     *
     * @param headers
     */
    private void addHeader(HashMap<String, String> headers) {
        int[] nonce = RandomUtil.randomInts(10);
        long timestamp = System.currentTimeMillis();
        headers.put("nonce", Arrays.toString(nonce));
        headers.put("timestamps", String.valueOf(timestamp));
        headers.put("accessKey", apiConfig.getAccessKey());
        headers.put("userAccount", String.valueOf(apiConfig.getUserAccount()));
        //md5加密,timestamp+nonce+accessKey+secretKey
        String sign = SecureUtil.md5(apiConfig.getAccessKey() + apiConfig.getSecretKey());
        headers.put("signs", sign);
    }

    public <T extends ApiResponse> T execute(ApiRequest<T> request, ApiObject model) {
        request.setModel(model);
        T response = execute(request);
        if (response==null){
            return null;
        }
        return response;
    }

    private <T extends ApiResponse> T execute(ApiRequest<T> request) {
        HttpResponse response = null;
        HashMap<String, String> header = new HashMap<>();
        addHeader(header);
        ApiMethod method = request.getMethod();
        HashMap<String, Object> param = new HashMap<>();
        if (method.equals(ApiMethod.GET)) {
            //封装请求参数
            ArrayList<Field> apiFields = apiFieldProcess.getApiFields(request.getClass());
            for (Field apiField : apiFields) {
                String fieldName = apiField.getAnnotation(ApiField.class).value();
                if (fieldName.isEmpty()) {
                    fieldName = apiField.getName();
                }
                param.put(fieldName, apiFieldProcess.getFieldValue(request, fieldName));
            }
            response = httpRequestUtil.sendGetRequest(request.getUrl(), param, header, RESPONSE_TIMEOUT_MILLISECONDS);
        }
        if (response != null) {
            //封装响应对象
            Class<T> responseClass = request.getResponseClass();
            T responseBody;
            try {
                responseBody = responseClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            responseBody.setBody(response.body());
            responseBody.setCode(response.getStatus());
            HashMap<String, Object> parseJson = JsonParseUtil.parseJson(responseBody.getBody());
            if (response.isOk()) {
                ArrayList<Field> apiFields = apiFieldProcess.getApiFields(responseBody.getClass());
                for (Field apiField : apiFields) {
                    String fieldName = apiField.getAnnotation(ApiField.class).value();
                    if (fieldName.isEmpty()) {
                        fieldName = apiField.getName();
                    }
                    //然后从hashmap中递归获取数据
                    Object value = jsonParseUtil.getValue(parseJson, fieldName);
                    apiFieldProcess.setFieldValue(responseBody, fieldName, value);
                }
                responseBody.setSubCode((Integer) parseJson.get("subCode"));
                responseBody.setMsg((String) parseJson.get("msg"));
            }
            return responseBody;
        }
        return null;
    }


    public ApiClient(ApiConfig apiConfig) {
        this.apiConfig = apiConfig;
        this.apiFieldProcess = new ApiFieldProcess();
        this.httpRequestUtil = new HttpRequestUtil();
        this.jsonParseUtil = new JsonParseUtil();
    }

    public ApiClient() {
        this.apiFieldProcess = new ApiFieldProcess();
        this.httpRequestUtil = new HttpRequestUtil();
        this.jsonParseUtil = new JsonParseUtil();
    }
}
